﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;

namespace RadioStationPOC
{
    public static class WCFHelper
    {
        // 创建并返回指定类型的双工 WCF 客户端实例
        public static T CreateDuplexClient<T, TCallback>(string endpointAddress, TCallback callbackInstance) where T : class
        {
            // 创建基于通道工厂的双工客户端
            var binding = new WSDualHttpBinding();

            binding.MaxReceivedMessageSize = Int32.MaxValue;
            binding.MaxBufferPoolSize = Int32.MaxValue;
            binding.OpenTimeout = new TimeSpan(0, 20, 0);
            binding.SendTimeout = new TimeSpan(0, 20, 0);
            //必须加上，否则传输大文件有问题..
            binding.ReaderQuotas.MaxDepth = int.MaxValue;
            binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
            binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
            binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
            binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
            //安全性
            binding.UseDefaultWebProxy = false;
            binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
            binding.Security.Mode = WSDualHttpSecurityMode.None;

            var endpoint = new EndpointAddress(endpointAddress);
            var context = new InstanceContext(callbackInstance);
            DuplexChannelFactory<T> factory = new DuplexChannelFactory<T>(context, binding, endpoint);
            foreach (OperationDescription op in factory.Endpoint.Contract.Operations)
            {
                DataContractSerializerOperationBehavior dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;
                if (dataContractBehavior != null)
                {
                    dataContractBehavior.MaxItemsInObjectGraph = Int32.MaxValue;
                }
            }
            // 创建和返回双工客户端实例
            return factory.CreateChannel();
        }

        // 关闭 WCF 客户端实例
        public static void CloseClient<T>(T client) where T : ICommunicationObject
        {
            try
            {
                if (client != null && client.State != CommunicationState.Closed)
                {
                    client.Close();
                }
            }
            catch (CommunicationException)
            {
                if (client != null && client.State != CommunicationState.Closed)
                {
                    client.Abort();
                }
            }
            catch (TimeoutException)
            {
                if (client != null && client.State != CommunicationState.Closed)
                {
                    client.Abort();
                }
            }
            catch (Exception)
            {
                if (client != null && client.State != CommunicationState.Closed)
                {
                    client.Abort();
                }
                throw;
            }
        }
    }
}
